package com.kuaiyin.utils;

import com.kuaiyin.dto.RequestDTO;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class CurlParser {

    private static final ObjectMapper mapper = new ObjectMapper();

    // 改进的正则表达式：支持多行匹配和特殊字符
    private static final Pattern METHOD_PATTERN = Pattern.compile("-X\\s+(\\w+)");
    private static final Pattern URL_PATTERN = Pattern.compile(
            "['\"]?((?:https?|ftp)://[^\\s'\"]+)['\"]?|" +    // 普通URL
                    "--url\\s+['\"]?((?:https?|ftp)://[^'\"\\s]+)['\"]?",  // 带--url参数的URL
            Pattern.CASE_INSENSITIVE | Pattern.DOTALL
    );

    private static final Pattern HEADER_PATTERN = Pattern.compile(
            "-H\\s+['\"]([^:]+):\\s*([^'\"]*?)['\"]|" +
                    "--header\\s+['\"]([^:]+):\\s*([^'\"]*?)['\"]",
            Pattern.CASE_INSENSITIVE | Pattern.DOTALL
    );

    private static final Pattern DATA_PATTERN = Pattern.compile(
            "(?:--data|--data-raw|--data-urlencode|--form)\\s+(?:['\"](.*?)['\"]|([^\\s]+))",
            Pattern.CASE_INSENSITIVE | Pattern.DOTALL
    );

    private static final Pattern JSON_BODY_PATTERN = Pattern.compile(
            "['\"](\\{.*?\\})['\"]",
            Pattern.CASE_INSENSITIVE | Pattern.DOTALL
    );

    private static final Set<String> SUPPORTED_METHODS =
            Set.of("GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS");

    private static final Pattern RAW_DATA_PATTERN = Pattern.compile(
            "--data-raw\\s+(['\"]?)([^{].*?)\\1(?:\\s|$)",
            Pattern.DOTALL
    );

    public static RequestDTO parse(String curlCommand) {
        RequestDTO dto = new RequestDTO();

        String url = extractUrl(curlCommand);
        dto.setPath(url);

        dto.setMethod(extractMethod(curlCommand));

        Map<String, Object> headers = extractHeaders(curlCommand);
        dto.setHeaders(headers);

        // 处理JSON数据
        String jsonBody = extractJsonBody(curlCommand);
        if (jsonBody != null && isJsonBody(headers)) {
            Map<String, Object> jsonMap = parseJsonToMap(jsonBody);
            if (jsonMap != null && !jsonMap.isEmpty()) {
                dto.setBody(jsonMap);
                return dto;
            }
        }

        // 处理其他数据形式
        Map<String, Object> form = extractFormBody(curlCommand);
        if (form != null && !form.isEmpty()) {
            dto.setBody(form);
            // 如果没有指定 content-type，默认设置为表单类型
            if (!headers.containsKey("content-type")) {
                headers.put("content-type", "application/x-www-form-urlencoded");
            }
        }

        return dto;
    }

    private static String extractMethod(String curlCommand) {
        Matcher matcher = METHOD_PATTERN.matcher(curlCommand);
        if (matcher.find()) {
            String method = matcher.group(1).toUpperCase();
            return SUPPORTED_METHODS.contains(method) ? method : "POST";
        }

        // 检测是否有数据体
        if (curlCommand.contains("--data") || curlCommand.contains("--data-raw") ||
                curlCommand.contains("--data-urlencode") || curlCommand.contains("--form")) {
            return "POST";
        }
        return "GET";
    }

    private static String extractUrl(String curlCommand) {
        // 改进的URL提取，支持多种格式
        Matcher matcher = URL_PATTERN.matcher(curlCommand);
        while (matcher.find()) {
            for (int i = 1; i <= matcher.groupCount(); i++) {
                if (matcher.group(i) != null && !matcher.group(i).isEmpty()) {
                    // 清理URL中的多余字符
                    String url = matcher.group(i).replaceAll("['\"\\\\]+", "");
                    return url.contains("http") ? url : "http://" + url;
                }
            }
        }

        // 回退：尝试从命令开头提取
        matcher = Pattern.compile("curl\\s+(?:['\"])?([^\\s'\"]+)(?:['\"])?",
                Pattern.CASE_INSENSITIVE | Pattern.DOTALL).matcher(curlCommand);
        if (matcher.find()) {
            return matcher.group(1);
        }

        return null;
    }

    private static Map<String, Object> extractHeaders(String curlCommand) {
        Map<String, Object> headers = new LinkedHashMap<>();
        Matcher matcher = HEADER_PATTERN.matcher(curlCommand);

        while (matcher.find()) {
            // 两种header格式处理
            String key = null;
            String value = null;

            if (matcher.group(1) != null) {
                key = matcher.group(1).trim().toLowerCase();
                value = matcher.group(2).trim();
            } else if (matcher.group(3) != null) {
                key = matcher.group(3).trim().toLowerCase();
                value = matcher.group(4).trim();
            }

            if (key != null && value != null && !key.isEmpty()) {
                // 特殊处理Cookie值中的多个Cookie
                if ("cookie".equals(key) && headers.containsKey(key)) {
                    headers.put(key, headers.get(key) + "; " + value);
                } else {
                    headers.put(key, value);
                }
            }
        }
        return headers;
    }

    private static String extractJsonBody(String curlCommand) {
        // 尝试提取格式化的JSON
        Matcher matcher = JSON_BODY_PATTERN.matcher(curlCommand);
        if (matcher.find()) {
            return matcher.group(1);
        }

        // 尝试从--data-raw中提取
        matcher = RAW_DATA_PATTERN.matcher(curlCommand);
        if (matcher.find()) {
            String potentialJson = matcher.group(2);
            // 检查是否是JSON格式
            if (potentialJson.trim().startsWith("{") && potentialJson.trim().endsWith("}")) {
                return potentialJson;
            }
        }

        return null;
    }

    private static Map<String, Object> extractFormBody(String curlCommand) {
        Map<String, Object> formMap = new LinkedHashMap<>();
        List<String> dataItems = new ArrayList<>();

        // 收集所有数据参数
        Matcher matcher = DATA_PATTERN.matcher(curlCommand);
        while (matcher.find()) {
            // 处理带引号和不带引号的格式
            if (matcher.group(1) != null) {
                dataItems.add(matcher.group(1));
            } else if (matcher.group(2) != null) {
                dataItems.add(matcher.group(2));
            }
        }

        // 处理所有数据项
        for (String dataItem : dataItems) {
            // 特殊处理JSON格式的数据
            if (dataItem.trim().startsWith("{") && dataItem.trim().endsWith("}")) {
                continue;
            }

            // 处理键值对格式
            if (dataItem.contains("=")) {
                int idx = dataItem.indexOf('=');
                String key = dataItem.substring(0, idx);
                String value = idx < dataItem.length() - 1 ? dataItem.substring(idx + 1) : "";

                // 特殊情况：值中包含未转义的引号
                if (value.startsWith("'") && value.endsWith("'")) {
                    value = value.substring(1, value.length() - 1);
                } else if (value.startsWith("\"") && value.endsWith("\"")) {
                    value = value.substring(1, value.length() - 1);
                }

                // 尝试解码键
                try {
                    key = URLDecoder.decode(key, StandardCharsets.UTF_8.name());
                } catch (Exception e) {
                    // 解码失败保持原样
                }

                formMap.put(key, value);
            } else {
                // 处理没有等号的情况
                formMap.put(dataItem.trim(), "");
            }
        }

        return formMap;
    }

    private static boolean isJsonBody(Map<String, Object> headers) {
        Object contentType = headers.get("content-type");
        if (contentType == null) return false;

        String contentTypeStr = contentType.toString().toLowerCase();
        return contentTypeStr.contains("application/json");
    }

    private static Map<String, Object> parseJsonToMap(String json) {
        try {
            return mapper.readValue(json, Map.class);
        } catch (Exception e) {
            log.error("JSON解析失败，返回空Map。JSON内容：{}", json, e);
            return Collections.emptyMap();
        }
    }
}